home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 001 / pibt40s2.arc / KCHECKAC.MOD < prev    next >
Text File  |  1987-09-13  |  12KB  |  323 lines

  1. (*----------------------------------------------------------------------*)
  2. (*      Check_Sliding_ACK  --- Check ACK State for sliding windows      *)
  3. (*----------------------------------------------------------------------*)
  4.  
  5. PROCEDURE Check_Sliding_ACK( Must_Get : BOOLEAN );
  6.  
  7. (*----------------------------------------------------------------------*)
  8. (*                                                                      *)
  9. (*     Procedure:  Check_Sliding_ACK                                    *)
  10. (*                                                                      *)
  11. (*     Purpose:    Checks ACK status for sliding windows                *)
  12. (*                                                                      *)
  13. (*     Calling Sequence:                                                *)
  14. (*                                                                      *)
  15. (*        Check_Sliding_ACK;                                            *)
  16. (*                                                                      *)
  17. (*----------------------------------------------------------------------*)
  18.  
  19. (* STRUCTURED *) CONST
  20.    Deadlock_Message : STRING[36] = 'Send cancelled -- apparent deadlock.';
  21.  
  22. VAR
  23.    A_Ch: CHAR;
  24.  
  25. (*----------------------------------------------------------------------*)
  26.  
  27. PROCEDURE Handle_Resend;
  28.  
  29. BEGIN (* Handle_Resend *)
  30.  
  31.    WITH Kermit_Queue[Rec_Packet_Num] DO
  32.       BEGIN
  33.  
  34.          Retry_Count        := SUCC( Retry_Count );
  35.          Send_Packet_Ptr    := ADDR( Sector_Data[Data_Slot] );
  36.          Send_Packet_Length := Data_Length;
  37. {
  38.          IF Kermit_Debug THEN
  39.             BEGIN
  40.                Write_Log('---Resending packet--- ' + IToS( Rec_Packet_Num ), FALSE, FALSE );
  41.                Write_Log('   Retry_Count = ' + IToS( Retry_Count ), FALSE, FALSE );
  42.                Write_Log('   Data_Length = ' + IToS( Data_Length ), FALSE, FALSE );
  43.             END;
  44. }
  45.          IF ( Retry_Count > Kermit_MaxTry ) THEN
  46.             BEGIN
  47.                Kermit_State       := Send_Break;
  48.                Kermit_Abort       := TRUE;
  49.                Kermit_Abort_Level := One_File;
  50.                Display_Kermit_Message('Too many retries for packet ' + IToS( Rec_Packet_Num ) );
  51.                EXIT;
  52.             END
  53.          ELSE
  54.             BEGIN
  55.                Display_Kermit_Message('Resending packet ' + IToS( Rec_Packet_Num ) );
  56.                Send_Packet;
  57.             END;
  58.       END;
  59.  
  60. END   (* Handle_Resend *);
  61.  
  62. (*----------------------------------------------------------------------*)
  63.  
  64. PROCEDURE Handle_ACK;
  65.  
  66. BEGIN (* Handle_ACK *)
  67.  
  68.    IF PacketInWindow THEN
  69.       BEGIN
  70.                                    (* Note that this packet has been ACKed. *)
  71.                                    (* If it is the lowest packet in the     *)
  72.                                    (* window, rotate the table.  We may     *)
  73.                                    (* need to rotate up more than one       *)
  74.                                    (* packet, depending upon how many of    *)
  75.                                    (* the following blocks have been ACK'd. *)
  76.  
  77.          ACK_OK               := TRUE;
  78.          Kermit_Window_Errors := 0;
  79.  
  80.          Kermit_Queue[Rec_Packet_Num].ACK_Flag := TRUE;
  81.  
  82.          IF ( Rec_Packet_Num = Kermit_Window_Bottom ) THEN
  83.             BEGIN
  84.                Kermit_Window_Bottom := SUCC( Kermit_Window_Bottom ) MOD 64;
  85.                Kermit_Window_Used   := PRED( Kermit_Window_Used );
  86.             END;
  87.  
  88.          WHILE ( ( Kermit_Window_Used > 0 ) AND
  89.                  ( Kermit_Queue[Kermit_Window_Bottom].ACK_Flag ) ) DO
  90.             BEGIN
  91.                Kermit_Window_Bottom := SUCC( Kermit_Window_Bottom ) MOD 64;
  92.                Kermit_Window_Used   := PRED( Kermit_Window_Used );
  93.             END;
  94.                                    (* Also check for interruption flags   *)
  95.                                    (* in data field:                      *)
  96.                                    (* 'X' = quit sending current file;    *)
  97.                                    (* 'Y' = quit batch of files.          *)
  98.  
  99.          IF ( Rec_Packet_Length > 0 ) THEN
  100.             CASE Rec_Packet_Ptr^[1] OF
  101.                'X': BEGIN
  102.                        Display_Kermit_Message_2('Receiver cancelled transfer of current file.');
  103.                        Kermit_Abort       := TRUE;
  104.                        Kermit_Abort_Level := One_File;
  105.                     END;
  106.                'Y': BEGIN
  107.                        Display_Kermit_Message_2('Receiver cancelled transfer of all files.');
  108.                        Kermit_Abort       := TRUE;
  109.                        Kermit_Abort_Level := All_Files;
  110.                     END;
  111.                ELSE;
  112.             END (* CASE *);
  113.  
  114.       END
  115.    ELSE
  116.       BEGIN
  117.          ACK_OK               := TRUE;
  118.          Kermit_Window_Errors := SUCC( Kermit_Window_Errors );
  119.          IF ( Kermit_Window_Errors > Kermit_MaxTry ) THEN
  120.             BEGIN
  121.                Display_Kermit_Message_2( Deadlock_Message );
  122.                Kermit_Abort       := TRUE;
  123.                Kermit_Abort_Level := One_File;
  124.                Kermit_State       := Send_Break;
  125.             END;
  126.       END;
  127.  
  128. END   (* Handle_ACK *);
  129.  
  130. (*----------------------------------------------------------------------*)
  131.  
  132. PROCEDURE Handle_NAK;
  133.  
  134. BEGIN (* Handle_NAK *)
  135.                                    (* Increment retry counter for this *)
  136.                                    (* packet if legitimate and resend  *)
  137.                                    (* it.                              *)
  138.    IF Async_Do_XonXoff THEN
  139.       BEGIN
  140.          Async_XOff_Received := FALSE;
  141.          IF Do_Status_Line THEN
  142.             Write_To_Status_Line( '             ', 65 );
  143.          Async_Send( CHR( XON ) );
  144.       END;
  145.  
  146.    Display_Kermit_Message('NAK for packet ' + IToS( Rec_Packet_Num ) + ' received.');
  147.  
  148.                                    (* If packet in window, try to resend it. *)
  149.                                    (* Else, increment overall error count.   *)
  150.    IF PacketInWindow THEN
  151.       BEGIN
  152.          Kermit_Window_Errors := 0;
  153.          Handle_Resend;
  154.       END
  155.    ELSE IF ( Rec_Packet_Num = ( SUCC( Kermit_Window_Top ) MOD 64 ) ) THEN
  156.       BEGIN
  157.          Rec_Packet_Num := Kermit_Window_Bottom;
  158.          Handle_Resend;
  159.       END
  160.    ELSE
  161.       BEGIN
  162.          Kermit_Window_Errors := SUCC( Kermit_Window_Errors );
  163.          IF ( Kermit_Window_Errors > Kermit_MaxTry ) THEN
  164.             BEGIN
  165.                Display_Kermit_Message_2( Deadlock_Message );
  166.                Kermit_Abort       := TRUE;
  167.                Kermit_Abort_Level := One_File;
  168.                Kermit_State       := Send_Break;
  169.             END;
  170.       END;
  171.  
  172. END   (* Handle_NAK *);
  173.  
  174. (*----------------------------------------------------------------------*)
  175.  
  176. PROCEDURE Handle_Error;
  177.  
  178. BEGIN (* Handle_Error *)
  179.  
  180.    Display_Kermit_Message('>> Error from remote Kermit <<');
  181.  
  182.    Kermit_Abort         := TRUE;
  183.    Kermit_Window_Errors := 0;
  184.  
  185.    GoToXY( 2 , Kermit_Mess2_Line );
  186.    WRITE( COPY( Rec_Packet_Ptr^, 1, Rec_Packet_Length ) );
  187.    ClrEol;
  188.  
  189.    Write_Log('Error from remote Kermit: ' +
  190.              COPY( Rec_Packet_Ptr^, 1, Rec_Packet_Length ) , FALSE , FALSE );
  191.  
  192.    IF ( Attended_Mode AND ( NOT Script_File_Mode ) ) THEN
  193.       BEGIN
  194.          GoToXY( 2 , Kermit_Mess3_Line );
  195.          WRITE('Hit any key to continue ... ');
  196.          Read_Kbd( A_Ch );
  197.          IF ( ORD( A_Ch ) = ESC ) AND KeyPressed THEN
  198.             READ( Kbd, A_Ch );
  199.       END;
  200.  
  201. END   (* Handle_Error *);
  202.  
  203. (*----------------------------------------------------------------------*)
  204.  
  205. BEGIN (* Check_Sliding_ACK *)
  206.                                    (* Assume bad packet to start *)
  207.    ACK_OK := FALSE;
  208.                                    (* If already aborted, quit.  *)
  209.    IF Kermit_Abort THEN
  210.       EXIT;
  211.                                    (* Pick up a packet           *)
  212.    Receive_Packet;
  213.  
  214.    Packet_Num := Rec_Packet_Num;
  215.  
  216. {
  217.    IF Kermit_Debug THEN
  218.       BEGIN
  219.  
  220.          Write_Log('---Check-Sliding-Ack---', FALSE, FALSE);
  221.  
  222.          CASE Kermit_Packet_Type OF
  223.             ACK_Pack  : Write_Log('ACK received', FALSE, FALSE);
  224.             NAK_Pack  : Write_Log('NAK received', FALSE, FALSE);
  225.             Error_Pack: Write_Log('Error received', FALSE, FALSE);
  226.             ELSE        Write_Log('Unknown received', FALSE, FALSE);
  227.          END (* CASE *);
  228.  
  229.          Write_Log('Rec_Packet_Num = ' + IToS( Rec_Packet_Num ), FALSE, FALSE);
  230.  
  231.          IF Packet_OK THEN
  232.             Write_Log('Packet_OK = TRUE', FALSE, FALSE)
  233.          ELSE
  234.             Write_Log('Packet_OK = FALSE', FALSE, FALSE);
  235.  
  236.       END;
  237. }
  238.                                    (* If we have to get a packet but *)
  239.                                    (* timed out instead, resend the  *)
  240.                                    (* earliest outstanding packet.   *)
  241.    IF Kermit_Abort THEN
  242.       ACK_OK := FALSE
  243.    ELSE IF ( ( NOT Packet_OK ) AND ( Must_Get ) ) THEN
  244.       BEGIN
  245.                                    (* Check XON/XOFF status here.  *)
  246.                                    (* Clear a received XOFF, since *)
  247.                                    (* it is probably bogus, and    *)
  248.                                    (* send XON to remote in case   *)
  249.                                    (* it received bogus XOFF.      *)
  250.  
  251.          IF Async_Do_XonXoff THEN
  252.             BEGIN
  253.                IF Async_XOff_Received THEN
  254.                   BEGIN
  255.                      Async_XOff_Received := FALSE;
  256.                      IF Do_Status_Line THEN
  257.                         Write_To_Status_Line( '             ', 65 );
  258.                   END;
  259.                Async_Send( CHR( XON ) );
  260.             END;
  261.  
  262.          Rec_Packet_Num := Kermit_Window_Bottom;
  263.  
  264.          WHILE ( ( Rec_Packet_Num <> Kermit_Window_Top ) AND
  265.                  ( Kermit_Queue[Rec_Packet_Num].ACK_Flag = TRUE ) ) DO
  266.             Rec_Packet_Num := SUCC( Rec_Packet_Num ) MOD 64;
  267.  
  268.          IF ( NOT Kermit_Queue[Rec_Packet_Num].ACK_Flag ) THEN
  269.             Handle_Resend;
  270.  
  271.          ACK_OK               := FALSE;
  272.  
  273.          Kermit_Window_Errors := SUCC( Kermit_Window_Errors );
  274.          IF ( Kermit_Window_Errors > Kermit_MaxTry ) THEN
  275.             BEGIN
  276.                Display_Kermit_Message_2( Deadlock_Message );
  277.                Kermit_Abort       := TRUE;
  278.                Kermit_Abort_Level := One_File;
  279.                Kermit_State       := Send_Break;
  280.             END;
  281.  
  282.       END
  283.    ELSE                            (* We got a packet. *)
  284.       BEGIN
  285.                                    (* Check if ACK or NAK packet received. *)
  286.                                    (* May also be error packet.            *)
  287.  
  288.          CASE Kermit_Packet_Type OF
  289.  
  290.                                    (* Make sure ACK is for legitimate block *)
  291.  
  292.             ACK_Pack   : Handle_ACK;
  293.             NAK_Pack   : Handle_NAK;
  294.             Error_Pack : Handle_Error;
  295.  
  296.                                    (* Something else -- don't ACK it *)
  297.             ELSE         BEGIN
  298.                             ACK_OK := FALSE;
  299.                             Display_Kermit_Message('Garbage packet received.');
  300.                             IF Async_Do_XonXoff THEN
  301.                                BEGIN
  302.                                   IF Async_XOff_Received THEN
  303.                                      BEGIN
  304.                                         Async_XOff_Received := FALSE;
  305.                                         IF Do_Status_Line THEN
  306.                                            Write_To_Status_Line( '             ', 65 );
  307.                                      END;
  308.                                   Async_Send( CHR( XON ) );
  309.                                END
  310.                          END;
  311.  
  312.          END (* CASE *)
  313.  
  314.       END;
  315.                                    (* Update count of bad packets *)
  316.    IF ( NOT ACK_OK ) THEN
  317.       Packets_Bad := Packets_Bad + 1;
  318.  
  319.                                    (* Update display *)
  320.    Update_Kermit_Display;
  321.  
  322. END    (* Check_Sliding_ACK *);
  323.